﻿using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Simple.Contracts.Contracts;
using Simple.Contracts.Models;
using Simple.Contracts.Models.Common;
using Simple.Contracts.Models.Common.File;
using Simple.Contracts.Models.Common.Page;
using Simple.Repository;
using Simple.Repository.SimpleEntitys;
using NPinyin;
using Simple.Common.Helpers;

namespace Simple.Services.Services
{
    /// <summary>
    /// 员工-服务类
    /// </summary>
    public class EmployeeService : BaseService, IEmployeeService
    {
        private readonly IConfiguration _configuration;
        private readonly ISmsService _smsService;
        public EmployeeService(FreeSqlCloud freeSqlCloud, IConfiguration configuration, CurrentAccount currentAccount, ISmsService smsService) : base(freeSqlCloud, currentAccount)
        {
            _configuration = configuration;
            _smsService = smsService;
        }

        /// <summary>
        /// 获取员工列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<Result<PageDto<EmployeeDto>>> List(EmployeeListInput input)
        {
            var employeeIds = new List<long>();
            if (input.roleIds != null && input.roleIds.Any())
            {
                employeeIds = await _simpleFreeSql.Select<RoleEmployee>()
                    .Where(x => x.CompanyId == _currentAccount.CompanyId && input.roleIds.Contains(x.RoleId) && x.IsDelete == 0)
                    .ToListAsync(x => x.EmployeeId);
            }

            var employees = await _simpleFreeSql.Select<Employee>()
                .Where(x => x.CompanyId == _currentAccount.CompanyId && x.IsDelete == 0)
                .WhereIf(!string.IsNullOrEmpty(input.name), x => x.Name.Contains(input.name!) || x.NamePinyinCapitalLetter.Contains(input.name!))
                .WhereIf(input.status.HasValue, x => x.Status == input.status!.Value)
                .WhereIf(employeeIds.Any(), x => employeeIds.Contains(x.Id))
                .Count(out var total)
                .Page(input.pageNum, input.pageSize)
                .ToListAsync();
            var roles = await _simpleFreeSql.Select<Role>().Where(x => x.CompanyId == _currentAccount.CompanyId && x.IsDelete == 0).ToListAsync();
            var roleEmployees = await _simpleFreeSql.Select<RoleEmployee>().Where(x => x.CompanyId == _currentAccount.CompanyId && x.IsDelete == 0).ToListAsync();

            var list = new List<EmployeeDto>();
            foreach (var x in employees)
            {
                var roleIds = roleEmployees.Where(m => m.EmployeeId == x.Id).Select(m => m.RoleId).ToList();
                var roleNames = roles.Where(m => roleIds.Contains(m.Id)).Select(x => x.Name).ToList();

                list.Add(new EmployeeDto()
                {
                    Address = x.Address,
                    AvatarUrl = x.AvatarUrl,
                    CreateTime = DateTime.Now.ToString("yyyy-MM-dd"),
                    Email = x.Email,
                    Gender = x.Gender,
                    Id = x.Id,
                    IdCard = x.IdCard,
                    IsDelete = x.IsDelete,
                    Name = x.Name,
                    Phone = x.Phone,
                    Status = x.Status,
                    PhotoUrls = string.IsNullOrEmpty(x.PhotoUrls) ? new List<ImageModel>() : JsonConvert.DeserializeObject<List<ImageModel>>(x.PhotoUrls),
                    roleIds = roleIds,
                    roleNames = roleNames,
                    ChineseZodiac = x.ChineseZodiac,
                    Educational = x.Educational,
                    HealthCertificateUrl = x.HealthCertificateUrl,
                    Height = x.Height,
                    HonorCertificateUrl = x.HonorCertificateUrl,
                    NursingCertificateUrl = x.NursingCertificateUrl,
                    RegisteredResidence = x.RegisteredResidence,
                    Weight = x.Weight,
                    WorkYear = x.WorkYear,
                    Brithday = x.Brithday.ToString("yyyy-MM-dd")
                });
            }
            return Result<EmployeeDto>.PageSuccess(list, total, input);
        }

        /// <summary>
        /// 保存员工信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<Result<string>> Save(EmployeeSaveInput input)
        {
            // 验证身份证
            if (!IdNumberHelper.CheckIdNumberFormat(input.IdCard))
            {
                return Result<string>.FriendlyReminder("省份证号码不符合要求");
            }

            // 保存员工信息
            long employeeId = 0;
            var passwordPlaintext = string.Empty;
            var employee = new Employee()
            {
                Address = input.Address,
                NamePinyin = Pinyin.GetPinyin(input.Name),
                NamePinyinCapitalLetter = Pinyin.GetInitials(input.Name),
                AvatarUrl = input.AvatarUrl,
                CompanyId = _currentAccount.CompanyId,
                Gender = IdNumberHelper.GetIdNumberGender(input.IdCard),
                Brithday = IdNumberHelper.GetIdNumberBirthday(input.IdCard),
                ChineseZodiac = IdNumberHelper.GetChineseZodiac(input.IdCard),
                CreateTime = DateTime.Now,
                Email = input.Email,
                IdCard = input.IdCard,
                IsDelete = 0,
                Name = input.Name,
                Phone = input.Phone,
                Status = 1,
                PhotoUrls = input.PhotoUrls != null ? JsonConvert.SerializeObject(input.PhotoUrls) : "[]",
                IsAdmin = 0,
                WorkYear = input.WorkYear,
                Weight = input.Weight,
                CreateBy = _currentAccount.EmployeeId,
                Educational = input.Educational,
                HealthCertificateUrl = input.HealthCertificateUrl,
                Height = input.Height,
                HonorCertificateUrl = input.HonorCertificateUrl,
                NursingCertificateUrl = input.NursingCertificateUrl,
                RegisteredResidence = input.RegisteredResidence,
                UpdateBy = _currentAccount.EmployeeId,
                UpdateTime = DateTime.Now
            };
            if (input.Id.HasValue)
            {
                // 更新员工信息
                var oldEmployee = await _simpleFreeSql.Select<Employee>().Where(x => x.Id == input.Id.Value && x.CompanyId == _currentAccount.CompanyId && x.IsDelete == 0).FirstAsync();
                if (oldEmployee == null)
                {
                    return Result<string>.FriendlyReminder("该员工不存在或已被删除");
                }

                // 以下信息不进行更新
                employee.Id = oldEmployee.Id;
                employee.CreateTime = oldEmployee.CreateTime;
                employee.Status = oldEmployee.Status;
                employee.Password = oldEmployee.Password;
                employee.PasswordPlaintext = oldEmployee.PasswordPlaintext;
                employee.IsAdmin = oldEmployee.IsAdmin;

                await _simpleFreeSql.Update<Employee>().SetSource(employee).ExecuteAffrowsAsync();
                employeeId = employee.Id;

            }
            else
            {
                // 新增员工
                passwordPlaintext = RandomHelper.GenerateNumericPassword(6);
                employee.PasswordPlaintext = passwordPlaintext;
                employee.Password = MD5Helper.GetMd5HashLowercase(passwordPlaintext);
                employeeId = await _simpleFreeSql.Insert<Employee>(employee).ExecuteIdentityAsync();
            }

            // 保存员工角色
            // 逻辑删除员工角色
            await _simpleFreeSql.Update<RoleEmployee>()
                .Set(x => x.IsDelete, 1)
                .Set(x => x.UpdateTime, DateTime.Now)
                .Set(x => x.UpdateBy, _currentAccount.EmployeeId)
                .Where(x => x.CompanyId == _currentAccount.CompanyId && x.EmployeeId == employeeId)
                .ExecuteAffrowsAsync();
            // 添加员工角色
            if (input.roleIds != null && input.roleIds.Any())
            {
                var entitys = input.roleIds.Select(roleId => new RoleEmployee()
                {
                    CompanyId = _currentAccount.CompanyId,
                    CreateBy = _currentAccount.EmployeeId,
                    CreateTime = DateTime.Now,
                    UpdateTime = DateTime.Now,
                    IsDelete = 0,
                    RoleId = roleId,
                    UpdateBy = _currentAccount.EmployeeId,
                    EmployeeId = employeeId,
                });
                await _simpleFreeSql.Insert<RoleEmployee>(entitys).ExecuteAffrowsAsync();
            }
            return Result<string>.Success(passwordPlaintext);
        }

        /// <summary>
        /// 删除员工
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<Result<bool>> Delete(EmployeeDeleteInput input)
        {
            await _simpleFreeSql.Update<Employee>()
                .Set(x => x.IsDelete, 1)
                .Set(x => x.UpdateBy, _currentAccount.EmployeeId)
                .Set(x => x.UpdateTime, DateTime.Now)
                .Where(x => x.CompanyId == _currentAccount.CompanyId && input.id.Contains(x.Id))
                .ExecuteAffrowsAsync();
            return Result<bool>.Success(true);
        }

        /// <summary>
        /// 重置密码
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<Result<string>> ResetPassword(EmployeeResetPasswordInput input)
        {
            var employee = await _simpleFreeSql.Select<Employee>().Where(x => x.CompanyId == _currentAccount.CompanyId && x.Id == input.id).FirstAsync();
            if (employee == null)
            {
                return Result<string>.FriendlyReminder("员工不存在或已被删除");
            }

            var passWordPlaintext = RandomHelper.GenerateNumericPassword(6);
            var passWordCiphertext = MD5Helper.GetMd5HashLowercase(passWordPlaintext);
            
            await _smsService.SendResetPassword(employee.Phone, passWordPlaintext);

            await _simpleFreeSql.Update<Employee>()
                .Set(x => x.Password, passWordCiphertext)
                .Set(x => x.PasswordPlaintext, passWordPlaintext)
                .Set(x => x.UpdateBy, _currentAccount.EmployeeId)
                .Set(x => x.UpdateTime, DateTime.Now)
                .Where(x => x.CompanyId == _currentAccount.CompanyId && input.id == x.Id)
                .ExecuteAffrowsAsync();
            return Result<string>.Success(passWordPlaintext);
        }

        /// <summary>
        /// 设置状态
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<Result<bool>> SetStatus(EmployeeSetStatusInput input)
        {
            await _simpleFreeSql.Update<Employee>()
                .Set(x => x.Status, input.Status)
                .Set(x => x.UpdateBy, _currentAccount.EmployeeId)
                .Set(x => x.UpdateTime, DateTime.Now)
                .Where(x => x.CompanyId == _currentAccount.CompanyId && input.id == x.Id)
               .ExecuteAffrowsAsync();
            return Result<bool>.Success(true);
        }
    }
}
